package com.jzt.b2b.controller;

import com.jzt.model.Merchandise;
import com.jzt.service.MerchandiseService;
import com.jzt.service.ServiceA;
import com.jzt.service.ServiceB;
import com.jzt.service.ServiceC;
import com.yvan.dsf.LogBackConfigLoader;
import com.yvan.dsf.anno.DsfConsumer;
import com.yvan.dsf.tracing.api.Span;
import com.yvan.dsf.tracing.client.ContextHolder;
import com.yvan.dsf.tracing.client.util.GUId;
import com.yvan.springmvc.ResultModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by luoyifan on 2017/11/21.
 */
@RestController
public class RootController {

    private static final Logger LOGGER = LoggerFactory.getLogger(RootController.class);

    @DsfConsumer
    private MerchandiseService merchandiseService;

    @DsfConsumer
    private ServiceA serviceA;

    @DsfConsumer
    private ServiceB serviceB;

    @DsfConsumer
    private ServiceC serviceC;

    @RequestMapping(value = "/log1.htm", method = RequestMethod.GET)
    public String log1() throws IOException {
        ResourceLoader resourceLoader = new DefaultResourceLoader();
        LogBackConfigLoader.load(resourceLoader.getResource("classpath:logback1.xml").getInputStream());
        return "OK";
    }

    @RequestMapping(value = "/log2.htm", method = RequestMethod.GET)
    public String log2() throws IOException {
        ResourceLoader resourceLoader = new DefaultResourceLoader();
        LogBackConfigLoader.load(resourceLoader.getResource("classpath:logback2.xml").getInputStream());
        return "OK";
    }

    @RequestMapping(value = "/log.htm", method = RequestMethod.GET)
    public String log() throws IOException {
        LOGGER.info("info_msg");
        return "OK";
    }

    @RequestMapping(value = {"/", "/index.htm"}, method = RequestMethod.GET)
    public ModelAndView index() {
        return new ModelAndView("/index.ftl");
    }


    @RequestMapping(value = "/merchandise/{id}.json", method = RequestMethod.GET)
    public Merchandise getMerchandiseById(@PathVariable("id") long id) {
        Merchandise merchandise = merchandiseService.getById(id);
        return merchandise;
    }

    @RequestMapping(value = "abc.txt", method = RequestMethod.GET)
    public String abc() {
        return merchandiseService.invokeABC();
    }

    @RequestMapping(value = "ba.txt", method = RequestMethod.GET)
    public String ba() {
        return merchandiseService.invokeBA();
    }

    @RequestMapping(value = "c.txt", method = RequestMethod.GET)
    public String c() {
        return merchandiseService.invokeC();
    }

    @RequestMapping(value = "seq.txt", method = RequestMethod.GET)
    public String seq() {
        String v = "";
        String traceId = GUId.singleton().nextId();
        ContextHolder.setTraceId(traceId);

        Span span = new Span();
        span.setId(GUId.singleton().nextId());
        span.setTraceId(traceId);
        span.setParentId(null);
        span.setServiceName("controller:com.jzt.b2b.controller.RootController");
        span.setName("com.jzt.b2b.controller.RootController.seq");
        ContextHolder.setSpan(span);

        for (int i = 0; i < 2; i++)
            v = serviceA.aFinish(v);

        for (int i = 0; i < 4; i++)
            v = serviceB.bFinish(v);

        for (int i = 0; i < 1; i++)
            v = serviceC.cFinish(v);
        return v;
    }

    @RequestMapping(value = "test.json", method = RequestMethod.GET)
    public ResultModel test(@RequestParam("size") int size) throws InterruptedException {
        AtomicInteger success = new AtomicInteger(0);
        AtomicInteger error = new AtomicInteger(0);
        AtomicInteger count = new AtomicInteger(0);

        ExecutorService executorServicePool = Executors.newFixedThreadPool(500);
        final CountDownLatch cdl = new CountDownLatch(size);
        long begin = System.currentTimeMillis();
        for (int i = 0; i < size; i++) {
            final long a = i;
            executorServicePool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        merchandiseService.getById(a);
                        success.incrementAndGet();

                    } catch (Exception e) {
                        e.printStackTrace();
                        error.incrementAndGet();

                    } finally {
                        cdl.countDown();
                        count.incrementAndGet();
                    }
                }
            });
        }
        //executorServicePool.shutdown();
        //executorService.awaitTermination(10, TimeUnit.MINUTES);
        cdl.await();//等待所有任务处理完
        long time = System.currentTimeMillis() - begin;
        ResultModel resultModel = new ResultModel();
        resultModel.put("耗时", (double) time / 1000 + " s");
        resultModel.put("平均", ((double) time) / size + " ms");
        resultModel.put("TPS", (double) size / ((double) time / 1000));
        resultModel.put("success", success.get());
        resultModel.put("error", error.get());
        resultModel.put("count", count.get());
        return resultModel;
    }
}
